### 1. Explain the concepts of call, apply, and bind in JavaScript. Provide examples.
  
  *Description*: call, apply, and bind are methods used to change the this value in functions.
   ```javascript
    const person = { name: 'Alice' };

    function greet(greeting) {
      console.log(`${greeting}, ${this.name}!`);
    }

    greet.call(person, 'Hello'); // Output: Hello, Alice!
    greet.apply(person, ['Hi']); // Output: Hi, Alice!

    const greetBound = greet.bind(person);
    greetBound('Hey'); // Output: Hey, Alice!
   ```

### 2. Explain the difference between `let`, `const`, and `var` in JavaScript.
    
    In JavaScript, `let`, `const`, and `var` are used to declare variables. Each has different scoping rules and reassignment capabilities, making them suitable for different use cases.

      #### 1. **`var`**:
        - `var` was traditionally used to declare variables in JavaScript.
        - Variables declared with `var` are function-scoped, meaning they are only accessible within the function they are declared in.
        - Variables declared with `var` can be redeclared and updated.

        ```javascript
        function exampleVar() {
          var x = 10;
          if (true) {
            var x = 20;  // This reassigns the existing variable 'x'
            console.log(x);  // Output: 20
          }
          console.log(x);  // Output: 20 (not 10)
        }
        ```

      #### 2. **`let`**:
        - Introduced in ES6, `let` allows block-scoping of variables, making them accessible only within the block they are defined in (e.g., if, for, while blocks).
        - Variables declared with `let` can be reassigned but cannot be redeclared in the same scope.

        ```javascript
        function exampleLet() {
          let y = 30;
          if (true) {
            let y = 40;  // This creates a new block-scoped variable 'y'
            console.log(y);  // Output: 40
          }
          console.log(y);  // Output: 30 (not affected by the inner 'y')
        }
        ```

      #### 3. **`const`**:
        - Also introduced in ES6, `const` is used to declare constants whose values cannot be reassigned.
        - Variables declared with `const` are block-scoped like `let`.
        - A `const` variable must be assigned a value during declaration and cannot be left uninitialized.

        ```javascript
        function exampleConst() {
          const z = 50;
          // z = 60;  // Error: Assignment to a constant variable
          console.log(z);  // Output: 50
        }
        ```

      In summary:
        - Use `var` for traditional function-scoped variables (but it's recommended to use `let` and `const` in modern JavaScript).
        - Use `let` when you need to reassign a variable's value within the same block.
        - Use `const` when you want to define a constant value that should not be reassigned.

        It's good practice to use `let` and `const` over `var` for better scoping and to avoid potential issues related to hoisting and unintended variable reassignment.

### 3. What is a closure in JavaScript? Provide an example.
   
   *Answer:*
   ```javascript
   function outer() {
     const message = 'Hello';
     function inner() {
       console.log(message);
     }
     return inner;
   }
   
   const innerFunc = outer();
   innerFunc();  // Output: 'Hello'
   ```

### 4. What is event delegation in JavaScript?
   *Answer:* Event delegation is a technique where a single event listener is attached to a common ancestor, allowing events to be handled for multiple children.

### 5. What is the difference between `==` and `===` in JavaScript?
   *Answer:* `==` checks for equality with type coercion, while `===` checks for strict equality without type coercion.

### 6. What is the purpose of the `async` and `await` keywords in JavaScript?
   *Answer:* `async` and `await` are features introduced in ES2017 (ES8) that make working with asynchronous code more readable and easier to manage. They are built on top of promises.

    #### 1. **`async`**:
      - `async` is used to declare that a function will work with promises and may use `await` within its body.
      - It allows a function to return a promise implicitly.
      - Functions marked with `async` always return a promise, even if you return a non-promise value.

      ```javascript
      async function asyncFunction() {
        return 42; // Equivalent to returning Promise.resolve(42)
      }
      ```

    #### 2. **`await`**:
      - `await` can only be used within an `async` function.
      - It is used to pause the execution of the function until a promise is resolved or rejected.
      - It "awaits" the result of a promise and returns the resolved value or throws an error for a rejected promise.

      ```javascript
      async function fetchUserData() {
        try {
          const response = await fetch('https://api.example.com/user');
          const data = await response.json();
          return data;
        } catch (error) {
          console.error('Error:', error);
        }
      }
      ```

    #### 3. **Difference from `.then()`**:
    - While both `await` and `.then()` handle asynchronous operations, the key difference lies in how they manage the flow of asynchronous code.
    - `.then()` is used with promises and is chaining-based, where each `.then()` function returns a promise and allows you to chain further operations.
    - `await`, on the other hand, allows for more synchronous-like code within `async` functions, making asynchronous code appear more linear and readable.

    ```javascript
    // Using .then()
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error('Error:', error));

    // Using await
    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error('Error:', error);
      }
    }
    ```
    In summary, `async` and `await` make asynchronous code look and behave more like synchronous code, enhancing readability and maintainability, especially when dealing with promises.

### 7. Explain what the `this` keyword refers to in JavaScript.
   
   *Answer:*
   `this` refers to the object on which a method is being called.

### 8. What is a promise in JavaScript? Provide an example of creating and using a promise.
   
   *Answer:*
   ```javascript
   const myPromise = new Promise((resolve, reject) => {
     setTimeout(() => {
       resolve('Promise resolved!');
     }, 2000);
   });

   myPromise.then((result) => {
     console.log(result);
   }).catch((error) => {
     console.error(error);
   });
   ```

### 9. What is a callback function in JavaScript? Provide an example.
   
   *Answer:*
   ```javascript
   function fetchData(callback) {
     setTimeout(() => {
       callback('Data fetched!');
     }, 2000);
   }

   fetchData((data) => {
     console.log(data);
   });
   ```

### 10. What is the difference between `null` and `undefined` in JavaScript?
    
    *Answer:*
    `null` is an assignment value representing no value or no object, while `undefined` is a primitive value automatically assigned to uninitialized variables.

### 11. What is event bubbling in JavaScript?
    
    *Answer:*
    Event bubbling is the propagation of an event from the target element up to its parent and higher ancestors in the DOM tree.

### 12. What is event.preventDefault()? Provide an example of its usage.
    Description: event.preventDefault() is used to prevent the default behavior of an event, such as form submission or link navigation.

    *Answer:*
    ```js
    const submitButton = document.getElementById('submitButton');
    submitButton.addEventListener('click', event => {
      event.preventDefault(); // Prevents form submission
      console.log('Form submission prevented.');
    });
    ```

### 13. What are arrow functions in JavaScript? Provide an example.
    *Answer:*
    ```javascript
    const add = (a, b) => a + b;
    console.log(add(2, 3));  // Output: 5
    ```

### 14. What is the purpose of the `localStorage` and `sessionStorage` objects in JavaScript?
    
    *Answer:*
    They provide a way to store key-value pairs in a web browser, with `localStorage` persisting even after the browser is closed and reopened, and `sessionStorage` existing only for the duration of the page session.

### 15. Explain event handling in JavaScript and provide an example of attaching an event listener.
    
    *Answer:*
    ```javascript
    const button = document.getElementById('myButton');

    button.addEventListener('click', () => {
      console.log('Button clicked!');
    });
    ```

### 16. What is the difference between `map()` and `forEach()` array methods in JavaScript?
    *Answer:* `map()` returns a new array with the results of a function applied to each element, while `forEach()` only iterates over the array and does not return a new array.

### 17. What is a RESTful API and how do you make a GET request using JavaScript?
    
    
    *Answer:*
    ```javascript
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error('Error:', error));
    ```

### 18. What is the purpose of the `use strict` directive in JavaScript?
    The "use strict" directive in JavaScript is used to enable a stricter interpretation of the code, catching common mistakes and preventing the use of certain error-prone features. When this directive is applied, the JavaScript engine enforces stricter rules for writing code.

    #### 1. Purpose:
      - It helps in writing more reliable and maintainable code by identifying and disallowing potentially error-prone behavior.
      - It prevents the accidental creation of global variables by enforcing block scope rules with `let` and `const`.
      - It disallows the use of certain language features that are deprecated or considered bad practice.

    #### 2. Example:
      ```javascript
      // Without "use strict"
      function withoutStrict() {
        variable = 10;  // This will create a global variable accidentally
        console.log(variable);
      }

      withoutStrict();  // Output: 10

      // With "use strict"
      function withStrict() {
        'use strict';
        variable = 20;  // This will throw a ReferenceError
        console.log(variable);
      }

      withStrict();  // Error: variable is not defined
      ```

      In the first example without "use strict," `variable` is mistakenly created as a global variable, which can lead to unexpected behavior and bugs in a larger codebase.

      In the second example with "use strict," attempting to assign a value to `variable` without declaring it with `var`, `let`, or `const` will throw a `ReferenceError`, indicating that `variable` is not defined. This helps catch potential bugs and encourages better coding practices.

      To enable "use strict" globally in a script, you can add it at the beginning of your JavaScript file or within a function. For modern JavaScript development, it's recommended to use "use strict" to enhance code quality and reduce the risk of errors.

### 19. Explain hoisting in JavaScript.
    *Answer:* 
    
    - Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their containing scope during the compile phase.

    ```js
    console.log(x);  // Output: undefined
    var x = 10;
    console.log(x);  // Output: 10
    ```

### 20. How do you handle errors in JavaScript? Provide an example of using a `try...catch` block.
    *Answer:*
    ```javascript
    try {
      // Code that may throw an error
      const result = 10 / 0;
      console.log(result);
    } catch (error) {
      console.error('An error occurred:', error.message);
    }
    ```

### 21. What are template literals in JavaScript? Provide an example.
  *Answer:*
  - Template literals are a feature introduced in ES6 that allow for easier string interpolation and multi-line strings. They are enclosed by backticks (`)        instead of single or double quotes.

    ```javascript
    const name = 'Alice';
    const greeting = `Hello, ${name}!`;
    console.log(greeting); // Output: Hello, Alice!
    ```

### 22. Explain the concept of "prototypal inheritance" in JavaScript.
  *Answer:*
  - Prototypal inheritance is a feature in JavaScript where objects can inherit properties and methods from other objects. This is achieved through the            prototype chain.

    ```javascript
    const animal = {
      speak() {
        console.log('Animal speaks');
      },
    };

    const dog = Object.create(animal);
    dog.speak(); // Output: Animal speaks
    ```

### 23. What are Promise.all() and Promise.race()? Provide examples of their usage.
  *Answer:*
  - Promise.all() takes an array of promises and returns a single promise that resolves when all of the promises in the array have resolved, or rejects if any     promise is rejected.
  - Promise.race() returns a promise that resolves or rejects as soon as one of the promises in the array resolves or rejects.

    ```javascript
    // Example of Promise.all
    Promise.all([
      Promise.resolve(1),
      Promise.resolve(2),
      Promise.resolve(3),
    ]).then(values => {
      console.log(values); // Output: [1, 2, 3]
    });

    // Example of Promise.race
    Promise.race([
      new Promise((resolve) => setTimeout(() => resolve('First'), 1000)),
      new Promise((resolve) => setTimeout(() => resolve('Second'), 500)),
    ]).then(result => {
      console.log(result); // Output: 'Second'
    });
    ```

### 24. What are higher-order functions in JavaScript? Provide an example.
  *Answer:* 
   - Higher-order functions are functions that take other functions as arguments or return functions as their result. This allows for more abstract and             reusable code.

    ```javascript
    function createMultiplier(multiplier) {
      return function(x) {
        return x * multiplier;
      };
    }

    const double = createMultiplier(2);
    console.log(double(5)); // Output: 10
    ```

### 25. What is the difference between shallow copy and deep copy?
  *Answer:*
  - A shallow copy duplicates the top-level properties of an object. If the properties are references to other objects, the references are copied, not the         actual objects.
  - A deep copy creates a new object and recursively copies all properties and their values.

  ```javascript
  const original = { a: 1, b: { c: 2 } };

  // Shallow copy
  const shallowCopy = Object.assign({}, original);
  shallowCopy.b.c = 3; // Changes 'c' in both objects
  console.log(original.b.c); // Output: 3

  // Deep copy
  const deepCopy = JSON.parse(JSON.stringify(original));
  deepCopy.b.c = 4; // Changes 'c' only in deepCopy
  console.log(original.b.c); // Output: 3
  ```

### 26. What is the purpose of setTimeout and setInterval in JavaScript? Provide examples.
  *Answer:*
  - setTimeout is used to execute a function after a specified delay (in milliseconds).
  - setInterval is used to repeatedly execute a function at specified intervals.

  ```javascript
  setTimeout(() => {
    console.log('Executed after 1 second');
  }, 1000);

  let count = 0;
  const intervalId = setInterval(() => {
    console.log('Count:', count++);
    if (count === 5) clearInterval(intervalId); // Stop after 5 counts
    }, 1000);
  ```

### 27. What are the JavaScript data types?
  *Answer:* 
  - JavaScript has several data types, including:

  - Primitive Types:

    1.  string: Represents text values.
    2.  number: Represents numeric values.
    3.  boolean: Represents true or false.
    4.  null: Represents an intentional absence of any object value.
    5.  undefined: Represents a variable that has been declared but not yet assigned a value.
    6.  symbol: Represents a unique identifier (introduced in ES6).
    7.  bigint: Represents integers with arbitrary precision (introduced in ES11).

  - Reference Types:

    1.  object: Represents complex data structures like arrays and objects.


### 28. What is the difference between synchronous and asynchronous programming in JavaScript?
  *Answer:*
  - Synchronous programming executes code in a sequential manner, where each operation must complete before the next one starts.
  - Asynchronous programming allows for operations to be executed independently of the main program flow, enabling code to run in the background while other       operations continue.

  ```javascript
  // Synchronous example
  console.log('First');
  console.log('Second');

  // Asynchronous example
  setTimeout(() => {
    console.log('Asynchronous operation');
  }, 1000);
  console.log('Third');
  ```

### 29. How can you check if a variable is an array in JavaScript?
  *Answer:*
  - You can use the Array.isArray() method to check if a variable is an array.

  ```javascript
  const arr = [1, 2, 3];
  console.log(Array.isArray(arr)); // Output: true

  const obj = {};
  console.log(Array.isArray(obj)); // Output: false
  ```

### 30. What is the difference between static and dynamic typing in JavaScript?
  *Answer:*
  - Static typing requires variable types to be declared explicitly, enabling type checking at compile time (not supported in 
    JavaScript).
  - Dynamic typing allows variables to hold values of any type without explicit type declaration, enabling type checking at runtime.


### 31. What are the main differences between ES5 and ES6?
1. Variable Declarations
ES5: Uses var (function-scoped).
ES6: Introduces let and const (block-scoped).

2. Arrow Functions
ES5: Regular functions with function.
ES6: Arrow functions (() => {}) with lexical this.

3. Template Literals
ES5: String concatenation with +.
ES6: Template literals using backticks for interpolation.

4. Destructuring Assignment
ES5: Manual extraction of values.
ES6: Simplified destructuring for arrays and objects.

5. Modules
ES5: No native support; relies on libraries.
ES6: Native import and export for modules.

6. Promises
ES5: Callbacks for async operations.
ES6: Promises for better async handling.

7. Iterators and Generators
ES5: No support for iterators.
ES6: Introduces iterators and generator functions.

### 32. How do you implement inheritance in JavaScript?

Inheritance can be implemented using prototypes or the class syntax introduced in ES6.
```javascript
function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() {
  console.log(`${this.name} makes a noise.`);
};

function Dog(name) {
  Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
  console.log(`${this.name} barks.`);
};
```
---
### 33. What is a memory leak in JavaScript, and how can you avoid it?
- A memory leak occurs when memory that is no longer needed is not released. Common causes include global variables, closures, and forgotten timers. 
  You can avoid memory leaks by ensuring proper cleanup of unused objects and avoiding unnecessary global variables.
---
